#ifndef DISPLAY_LIST_UTILS_H_
#define DISPLAY_LIST_UTILS_H_

class DisplayListsUtils{
	private:
		GLuint dlhandle;
		GLuint dlAxis;
		GLuint dlGrid;
		GLuint dlAxis2DTop;
		GLuint dlAxis2DHeight;

	public:
		void createDisplayLists(){
			dlhandle = glGenLists(3);
			dlAxis=dlhandle+0;
			dlGrid=dlhandle+1;
			dlAxis2DTop=dlhandle+2;
			dlAxis2DHeight=dlhandle+3;

			// Generaci�n de las Display Lists
			glNewList(dlAxis, GL_COMPILE);
				drawAxis();
			glEndList();
			glNewList(dlGrid, GL_COMPILE);
				drawXYGrid();
			glEndList();
			glNewList(dlAxis2DTop, GL_COMPILE);
				drawAxis2DTopView();
			glEndList();
			glNewList(dlAxis2DHeight, GL_COMPILE);
				drawAxis2DHeightView();
			glEndList();
		}

		static void drawAxis(){
			glDisable(GL_LIGHTING);
			glBegin(GL_LINES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(15.0, 0.0, 0.0);
				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(0.0, 15.0, 0.0);
				// Z
				glColor3f(0.0, 0.0, 1.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(0.0, 0.0, 15.0);
			glEnd();
			glEnable(GL_LIGHTING);
		}

		static void drawAxis2DTopView(){
			glDisable(GL_LIGHTING);
			glPushMatrix();
				glTranslatef(0.5f,0.5f,0.0f);
				glBegin(GL_LINES);
					// X
					glColor3f(1.0f, 0.0f, 0.0f);
					glVertex3f(0.0f, 0.0f, 0.0f);
					glVertex3f(0.25f, 0.0f, 0.0f);
					// Y
					glColor3f(0.0f, 1.0f, 0.0f);
					glVertex3f(0.0f, 0.0f, 0.0f);
					glVertex3f(0.0f, 0.25f, 0.0f);
					glEnd();

				glBegin(GL_TRIANGLES);
					// X
					glColor3f(1.0f, 0.0f, 0.0f);
					glVertex3f(0.27f, 0.0f, 0.0f);
					glVertex3f(0.23f, -0.01f, 0.0f);
					glVertex3f(0.23f, 0.01f, 0.0f);

					// Y
					glColor3f(0.0f, 1.0f, 0.0f);
					glVertex3f(0.0f, 0.27f, 0.0f);
					glVertex3f(0.01f, 0.23f, 0.0f);
					glVertex3f(-0.01f, 0.23f, 0.0f);
				glEnd();

				glRasterPos3f(0.05, 0.25, 0.0);
				glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'y');
				glRasterPos3f(0.25, 0.05, 0.0);
				glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'x');
				glEnable(GL_LIGHTING);
			glPopMatrix();
		}

		static void drawAxis2DHeightView(){
			glDisable(GL_LIGHTING);
			glBegin(GL_LINES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.03, 0.07, 0.0);
				glVertex3f(0.25, 0.07, 0.0);

				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.07, 0.03, 0.0);
				glVertex3f(0.07, 0.25, 0.0);
			glEnd();
			glBegin(GL_TRIANGLES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.27, 0.07, 0.0);
				glVertex3f(0.23, 0.06, 0.0);
				glVertex3f(0.23, 0.08, 0.0);

				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.07, 0.27, 0.0);
				glVertex3f(0.06, 0.23, 0.0);
				glVertex3f(0.08, 0.23, 0.0);
			glEnd();

			glRasterPos3f(0.09, 0.25, 0.0);
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'z');
			glRasterPos3f(0.25, 0.09, 0.0);
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'u');
			glEnable(GL_LIGHTING);
		}

		static void drawXYGrid(){
			int i;
			glDisable(GL_LIGHTING);
			glColor3f(0.35, 0.15, 0.1);
			glBegin(GL_LINES);
			for(i=-20; i<21; i++)
			{
				glVertex3f(i, -20.0, 0.0);
				glVertex3f(i,  20.0, 0.0);
				glVertex3f(-20.0, i, 0.0);
				glVertex3f( 20.0, i, 0.0);
			}
			glEnd();
			glEnable(GL_LIGHTING);
		}

		static DisplayListsUtils& instance(){
			static DisplayListsUtils instance;
			return instance;
		}
		/*static void drawColumn(Column& c){
			glPushMatrix();
				glTranslatef(c.getPosition().x1,c.getPosition().x2,0);
				glRotatef(c.getTheta(),0,0,1);
				glScalef(c.getDepth(),c.getWidth(),c.getHigh());
				drawHalfColumn(c);
				glScalef(1.0,-1.0,1.0);
				drawHalfColumn(c);
			glPopMatrix();
		}*/

		static void drawHalfColumn(){
			Point points[48]={Point(0.125,-0.25,0), Point(-0.125,-0.25,0),Point(-0.125,-0.5,0),Point (0.125,-0.5,0),
			Point(-0.125,-0.5,0),Point(-0.125,-0.25,0.50),Point(0.125,-0.25,0.50),Point(0.125,-0.5,0),
			Point(0.125,-0.25,0.50),Point(0.125,0,0.50),Point(-0.125,0,0.50),Point(-0.125,-0.25,0.50),
			Point(0.125,-0.5,0),Point(0.125,-0.25,0),Point(0.125,0,0.50),Point(0.125,-0.25,0.50),
			Point(-0.125,-0.5,0),Point(-0.125,-0.25,0),Point(-0.125,0,0.50),Point(-0.125,-0.25,0),
			Point(0.125,-0.25,0),Point(-0.125,-0.25,0),Point(-0.125,0,0.50),Point(0.125,0,0.50),
			/*fin del "Cubo"*/
			/*Comienzo de piramide*/
			Point(0.125,-0.25,0.50),Point(-0.125,-0.25,0.50),Point(0,0,1),
			Point(-0.125,-0.25,0.50),Point(-0.125,0,0.50),Point(0,0,1),
			Point(-0.125,0,0.5),Point(0.125,0,0.5),Point(0,0,1),
			Point(0.125,-0.25,0.5),Point(0.125,0,0.5),Point(0,0,1),
			//Linea q cruza
			//Point(0.125,-0.15,0.2),Point(0.125,-0.15,0.25),Point(-0.125,-0.15,0.25),Point(-0.125,-0.15,0.2),
			Point(0.125,-0.15,0.2),Point(0.125,-0.15,0.25),Point(0.125,0,0.25),Point(0.125,0,0.2),
			Point(-0.125,-0.15,0.2),Point(-0.125,-0.15,0.25),Point(-0.125,0,0.25),Point(-0.125,0,0.2),
			Point(0.125,-0.15,0.25),Point(-0.125,-0.15,0.25),Point(-0.125,0,0.25),Point(0.125,0,0.25)
			};

			glColor3f(0.55,0.6,0.5);
			glBegin(GL_QUADS);
				for (unsigned int i=36;i<48;i++)
					glVertex3f(points[i].x1,points[i].x2,points[i].x3);
			glEnd();
			glColor3f(0.3,0.3,0.25);
			glBegin(GL_QUADS);
				for (unsigned int i=0;i<6*4;i++)
					glVertex3f(points[i].x1,points[i].x2,points[i].x3);
			glEnd();

			glBegin(GL_TRIANGLES);
				for (unsigned int i=24;i<36;i++)
					glVertex3f(points[i].x1,points[i].x2,points[i].x3);
			glEnd();
		}


		static void drawCube(Point points[4]){
			// Tapas
			glBegin(GL_QUADS);
				//Tapa 1
				glColor3f(1,0,0);
				glVertex3f(points[0].x1,points[0].x2,points[0].x3);
				glColor3f(0,1,0);
				glVertex3f(points[1].x1,points[1].x2,points[1].x3);
				glColor3f(0,0,1);
				glVertex3f(points[2].x1,points[2].x2,points[2].x3);
				glColor3f(0,1,1);
				glVertex3f(points[3].x1,points[3].x2,points[3].x3);
				glColor3f(1,0,0);
				// Tapa 2
				glVertex3f(points[4].x1,points[4].x2,points[4].x3);
				glColor3f(0,1,0);
				glVertex3f(points[5].x1,points[5].x2,points[5].x3);
				glColor3f(0,0,1);
				glVertex3f(points[6].x1,points[6].x2,points[6].x3);
				glColor3f(0,1,1);
				glVertex3f(points[7].x1,points[7].x2,points[7].x3);
			glEnd();

			for(unsigned int c=0;c<4;c++){
				glBegin(GL_QUADS);
					glColor3f(1,0,0);
					glVertex3f(points[c+0].x1,points[c+0].x2,points[c+0].x3);
					glColor3f(0,1,0);

					if((c+1)<4){
						glVertex3f(points[c+1].x1,points[c+1].x2,points[c+1].x3);
						glColor3f(0,0,1);
						glVertex3f(points[c+5].x1,points[c+5].x2,points[c+5].x3);
						glColor3f(0,1,1);
						glVertex3f(points[c+4].x1,points[c+4].x2,points[c+4].x3);
					}else{
						glVertex3f(points[0].x1,points[0].x2,points[0].x3);
						glColor3f(0,0,1);
						glVertex3f(points[4].x1,points[4].x2,points[4].x3);
						glColor3f(0,1,1);
						glVertex3f(points[7].x1,points[7].x2,points[7].x3);
					}
					glEnd();
			}
		}

		GLuint getAxisHandle(){
			return this->dlAxis;
		}

		GLuint getGridHandle(){
			return this->dlGrid;
		}

		GLuint getAxis2DTopHandle(){
			return this->dlAxis2DTop;
		}

		GLuint getAxis2DHeightHandle(){
			return this->dlAxis2DHeight;
		}

	private:
		DisplayListsUtils(){
			dlhandle=0;
			dlAxis=0;
			dlGrid=0;
			dlAxis2DTop=0;
			dlAxis2DHeight=0;
		}
		DisplayListsUtils(const DisplayListsUtils& u){}

		void operator=(const DisplayListsUtils& u){}
};

#endif /* DISPLAY_LIST_UTILS_H_ */
